/*
 * Copyright (C) 2012 artit91
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package rpg.entities.eventhandlers;

import inventory.Inventory;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.Random;
import java.util.logging.Logger;
import rpg.Game;
import rpg.Location;
import rpg.RPG;
import rpg.entities.Entity;
import rpg.entities.Sprite;
import rpg.entities.factories.CreatureFactory;
import rpg.entities.factories.SpriteFactory;
import rpg.entities.properties.CreatureProperty;
import rpg.gfx.gui.Bar;
import rpg.gfx.Bitmap;
import rpg.console.Console;
import rpg.gfx.Screen;
import rpg.gfx.gui.Text;

/**
 *
 * @author artit91
 */
public class PlayerEvents extends EventHandler {

    public static final int UP = 0;
    public static final int LEFT = 1;
    public static final int DOWN = 2;
    public static final int RIGHT = 3;
    private Inventory inventory;
    private int energy = 100;
    private int dir;
    private boolean moving;
    private boolean running;
    private boolean resting;
    private static int animphase;
    private Bar energyBar;
    private Bar healthBar;
    private Bar xpBar;
    private Text levelText;
    private int animDelay = 5;
    private int restDelay = 20;
    private int healdelay = 100;
    private int consumeDelay = 5;
    private int damageDelay = 0;
    private CreatureFactory cf;
    private CreatureProperty cp;
    private boolean immortal = false;

    public PlayerEvents(final CreatureFactory cf) {
        this.cf = cf;
        this.cp = (CreatureProperty) cf.getProp();
        energyBar = new Bar(100, 6, 0xffff00, 0x0, 100, 100);
        healthBar = new Bar(100, 6, 0xff0000, 0x1, 150, 150);
        xpBar = new Bar(500, 6, 0x00ff00, 0x1, 100, 0);
        levelText = new Text(0xff00, 500, 20);
        Screen.getInstance().gui.addElement(energyBar, 10, 460);
        Screen.getInstance().gui.addElement(healthBar, 10, 450);
        Screen.getInstance().gui.addElement(xpBar, 120, 460);
        Screen.getInstance().gui.addElement(levelText, 120, 435);
    }

    @Override
    public Bitmap getDrawGraphics() {
        if (moving) {
            return cf.bitmaps[animphase % 2 + dir * 3 + 1];
        } else {
            return cf.bitmaps[dir * 3];
        }
    }

    private void checkControls() {
        if (RPG.keylistener.isKeyDown(KeyEvent.VK_ESCAPE)) {
            RPG.rpg.exitToMenu();
        }
        int moves = 0;
        int tmp = -1;

        running = RPG.keylistener.isKeyDown(KeyEvent.VK_SHIFT);
        int speed = (running && energy > 0 && !resting) ? 3 : 2;
        if (RPG.keylistener.isKeyDown2(KeyEvent.VK_0)) {
            RPG.keylistener.clearCache();
            Console con = Console.getInstance();
            con.toggle();
        }
        if (!Console.getInstance().isVisible()) {
            if (RPG.keylistener.isKeyDown(KeyEvent.VK_A) || RPG.keylistener.isKeyDown(KeyEvent.VK_LEFT)) {
                if (cp.getLocation().move(Location.LEFT, speed)) {
                    dir = LEFT;
                    moves++;
                } else {
                    tmp = LEFT;
                }
            } else if (RPG.keylistener.isKeyDown(KeyEvent.VK_D) || RPG.keylistener.isKeyDown(KeyEvent.VK_RIGHT)) {
                if (cp.getLocation().move(Location.RIGHT, speed)) {
                    dir = RIGHT;
                    moves++;
                } else {
                    tmp = RIGHT;
                }
            }
            if (RPG.keylistener.isKeyDown(KeyEvent.VK_W) || RPG.keylistener.isKeyDown(KeyEvent.VK_UP)) {
                if (cp.getLocation().move(Location.UP, speed)) {
                    dir = UP;
                    moves++;
                } else {
                    tmp = UP;
                }
            } else if (RPG.keylistener.isKeyDown(KeyEvent.VK_S) || RPG.keylistener.isKeyDown(KeyEvent.VK_DOWN)) {
                if (cp.getLocation().move(Location.DOWN, speed)) {
                    dir = DOWN;
                    moves++;
                } else {
                    tmp = DOWN;
                }
            }
            if (RPG.keylistener.isKeyDown(KeyEvent.VK_SPACE)) {
                /*
                 * interact();
                 */
            }

            if (RPG.keylistener.isKeyDown(KeyEvent.VK_CONTROL)) {
                attack();
            }

            if (RPG.keylistener.isKeyDown(KeyEvent.VK_PRINTSCREEN) || RPG.keylistener.isKeyDown(KeyEvent.VK_F12)) {
                RPG.rpg.screenShot();
            }

            if (RPG.keylistener.getCache().contains("chicken")) {
                for (int i = 0; i < 50; ++i) {
                    SpriteFactory.newInstance('c', cp.getLocation().getMap(), cp.getLocation().getMapCoordinate());
                }
                RPG.keylistener.clearCache();
            }

            if (RPG.keylistener.getCache().contains("iddqd")) {
                immortal = !immortal;
                RPG.keylistener.clearCache();
            }

            if (RPG.keylistener.isKeyDown(KeyEvent.VK_PRINTSCREEN) || RPG.keylistener.isKeyDown(KeyEvent.VK_F12)) {
                RPG.rpg.screenShot();
            }
            moving = moves > 0;
            if (moving && running && energy > 0 && !resting) {
                consumeDelay--;
                if (consumeDelay <= 0) {
                    consumeDelay = 5;
                    energy -= 1;
                    if (energy < 2) {
                        resting = true;
                    }
                }
            }
            if (!moving && tmp >= 0) {
                dir = tmp;
            }
        }


    }

    @Override
    public void tick() {
        animDelay--;
        if (animDelay <= 0) {
            animDelay = 5;
            animphase++;
            animphase %= 2;
        }
        healdelay--;
        if (healdelay <= 0) {
            healdelay = 100;
            if (!running || resting) {
                if (cp.getHealth() < 150) {
                    int from = cp.getHealth();
                    cp.setHealth(cp.getHealth() + 1);
                    if (from < 30 && energy >= 30) {
                        resting = false;
                    }
                }
            }
        }
        restDelay--;
        if (restDelay <= 0) {
            restDelay = 20;
            if (!running || resting) {
                if (energy < 100) {
                    int from = energy;
                    energy++;
                    if (from < 30 && energy >= 30) {
                        resting = false;
                    }
                }
            }
        }
        if (damageDelay > 0) {
            damageDelay--;
        }
        checkControls();
        checkMap();
        energyBar.setVal(energy);
        healthBar.setVal(cp.getHealth());
        levelText.setText("" + cp.getLevel());
        if (cp.getLevel() <= 40) {
            xpBar.setVal(cp.getCurrXP());
        } else {
            xpBar.setColor(0xeac117);
        }
    }

    private void checkMap() {
        if (cp.getLocation().getX() < 320) {
            cf.setxRenderOffset(320 - cp.getLocation().getX());
        } else if (cp.getLocation().getX() > Game.getInstance().getActual().getWidth() * 64 - 320) {
            cf.setxRenderOffset((Game.getInstance().getActual().getWidth() * 64 - 320) - cp.getLocation().getX());
        } else {
            cf.setxRenderOffset(0);
        }

        if (cp.getLocation().getY() < 240) {
            cf.setyRenderOffset(240 - cp.getLocation().getY());
        } else if (cp.getLocation().getY() > Game.getInstance().getActual().getHeight() * 64 - 240) {
            cf.setyRenderOffset((Game.getInstance().getActual().getHeight() * 64 - 240) - cp.getLocation().getY());
        } else {
            cf.setyRenderOffset(0);
        }
    }

    public void attack() {
        if (damageDelay != 0) {
            return;
        }
        List<Entity> entity = Game.getInstance().getActual().getEntity(cp.getLocation().getTile(dir));
        for (Entity e : entity) {
            if (e instanceof Sprite) {
                damageDelay = 30;
                Random r = new Random();
                int dmg = r.nextInt(10) + 10;
                boolean damage = ((Sprite) e).getEh().damage(cf, dmg);
                if (damage) {
                    SpriteFactory.remove(((Sprite) e).getProp().getId());
                    cp.accountXp(((CreatureProperty) (((Sprite) e).getProp())).getLevel());

                }
            }
        }
    }

    @Override
    public boolean damage(Sprite causer, int dmg) {
        if (immortal) {
            dmg = 0;
        }
        if (cp.getHealth() - dmg <= 0) {
            cp.setHealth(0);
            RPG.rpg.playerDeath();
        } else {
            cp.setHealth(cp.getHealth() - dmg);
            healthBar.setVal(cp.getHealth());
        }
        //lastDamagedBy = causer;
        return cp.getHealth() == 0;
    }

    public Inventory getInventory() {
        return inventory;
    }

    public void setDir(int dir) {
        this.dir = dir;
    }

    public void setInventory(Inventory inventory) {
        this.inventory = inventory;
    }
    private static final Logger LOG = Logger.getLogger(PlayerEvents.class.getName());

    public Bar getEnergyBar() {
        return energyBar;
    }

    public Bar getHealthBar() {
        return healthBar;
    }
}
